
/*
document:
- StubApiCStruct
- StubApiCShortIntegerConstant(_onearg)
*/


StubApiCStart():=
[
  cconsts := "";
  cfuncs  := "";
  cadders := "";
  cincludes:="";
  cremarks:="";
  cstructs:={};
];



StubApiCStruct(name) := StubApiCStruct(name,"PlatFree");
StubApiCStruct(name,free):=
[
  cremarks:=cremarks:
  "----------------------------------------":Nl():
  "Declared struct ":name:Nl();
  cstructs[name]:=free;
];


StubApiCRemark(text):=
[
  cremarks:=cremarks:text:Nl();
];

StubApiCSetEnv(string):=
[
  cadders := cadders: "  ":string:"(aEnvironment);
  ";
];

StubApiCShortIntegerConstant(const,val) :=
[
  cremarks:=cremarks:
  "----------------------------------------":Nl():
  "Constant ":const:" referred to in the library as ":val:
"
";
  cconsts:= cconsts:PatchString(
"  SetShortIntegerConstant(aEnvironment, <?Write(const);?>, <?WriteString(val  );?>);
");
];

/* Use this one for defines */
StubApiCShortIntegerConstant(_onearg) <--
  StubApiCShortIntegerConstant(onearg,onearg);



StubApiCInclude(file):=
[
cincludes:=cincludes : "#include ":file:"
";
];

CArgsGet(args_IsList) <--
[
  Local(arg,i);
  i:=1;
  ForEach(arg,args)
  [
    CArgsGet(CArgType(arg),i);
    i++;
  ];
];

10 # CArgType(arg_IsList)<-- arg[1];
20 # CArgType(arg_IsString)<-- arg;

10 # CArgName(arg_IsList,_i)_(Length(arg)>1) <-- arg[2];
20 # CArgName(_arg,_i) <-- "arg":String(i);

20 # CArgsGet("int",_i) <--
[
 

 WriteString(PatchString(
"  ShortIntegerArgument(g, <? WriteString(\"arg\":String(i)); ?>, LispTrue);
"));
];


20 # CArgsGet("double",_i) <--
[
 WriteString(PatchString(
"  DoubleFloatArgument(g,<? WriteString(\"arg\":String(i)); ?>,LispTrue);
"));
];

20 # CArgsGet("input_string",_i) <--
[
 WriteString(PatchString(
"  InpStringArgument(g,<? WriteString(\"arg\":String(i)); ?>,LispTrue);
"));
];

30 # CArgsGet(name_IsString,_i)_(cstructs[name] != Empty) <--
[
 WriteString(PatchString(
"  VoidStructArgument(<?WriteString(name);?>,g,<? WriteString(\"arg\":String(i)); ?>,LispTrue,<?Write(name);?>);
"));
];




100 # CArgsGet(_a,_i) <-- Check(False,"Argument type ":a:" not supported");

CCall(returntype,fname,args):=
[
 WriteString(fname);
 WriteString("(");
 Local(i);
 For (i:=1,i<=Length(args),i++)
     [
      If(i>1,WriteString(", "));
     WriteString("arg":String(i));
     ];
 WriteString(");");
];

10  # CReturnResult("void") <--
    WriteString("  InternalTrue(aEnvironment,aResult);");

10  # CReturnResult("int") <--
    WriteString("  ReturnShortInteger(aEnvironment,aResult,r);");
10  # CReturnResult("double") <--
    WriteString("  ReturnDoubleFloat(aEnvironment,aResult,r);");

20  # CReturnResult(name_IsString)_(cstructs[name] != Empty)<--

    WriteString("  ReturnVoidStruct(aEnvironment, aResult,":String(name):", r,":cstructs[name]:");");

100 # CReturnResult(_r) <-- Check(False,"Return type ":r:" not supported");


10  # CCallContain("void") <-- True;
10  # CCallContain("int") <-- WriteString("int r = ");
10  # CCallContain("double") <-- WriteString("double r = ");

20  # CCallContain(name_IsString)_(cstructs[name] != Empty)<--
      WriteString("void* r = ");
100 # CCallContain(_r) <-- Check(False,"Return type ":r:" not supported");



funcstring:=
"
static void base_<? WriteString(fname); ?>(LispEnvironment& aEnvironment, LispPtr& aResult,
                           LispPtr& aArguments)
{
  /* Obtain arguments passed in. */
  LispArgGetter g(aEnvironment, aArguments);
<?
CArgsGet(args);
?>  g.Finalize(<?Write(Length(args));?>);

  /* Call the actual function. */
<?CCallContain(returntype);?> <?CCall(returntype,fname,args); ?>

/* Return result. */
<?
CReturnResult(returntype);
?>
}
";


cadderstring:=
"  aEnvironment.SetCommand(base_<? WriteString(fname); ?>, <? Write(fname2); ?>);
";

fileapi:=
"
/* This file was automatically generated with cstubgen.
*/
#include \"lisptype.h\"
#include \"lispenvironment.h\"
#include \"lispatom.h\"
#include \"standard.h\"
#include \"arggetter.h\"
#include \"lispplugin.h\"
#include \"platmath.h\"
#include \"stubs.h\"
#include \"genericstructs.h\"

<?
WriteString(cincludes);
?>
<?
WriteString(cfuncs);
?> 


class ThisPlugin : public LispPluginBase
{
public:
    virtual void Add(LispEnvironment& aEnvironment);
};
void ThisPlugin::Add(LispEnvironment& aEnvironment)
{
<?
WriteString(cconsts);
?>
<?
WriteString(cadders);
?>}


extern \"C\" {
LispPluginBase* maker(void)
{
    return new ThisPlugin;
}

};

";

StubApiCDocumentFunction(returntype,fname,fname2,args):=
[
  cremarks:=cremarks:
  "----------------------------------------":Nl():
  "Function ":fname2:Nl():" (referred to within the original library as ":fname:
  ")":Nl():" with return type ":CArgType(returntype):" and arguments:
";
  Local(arg,i);
  i:=1;
  ForEach(arg,args)
  [
    cremarks:=cremarks:String(i):". ":CArgType(arg):" ":CArgName(arg,i):Nl();
    i++;
  ];

];

StubApiCFunction(returntype,fname,args) :=
[
  Local(fname2);
  cfuncs:= cfuncs:PatchString(funcstring);
  fname2:=fname;
  cadders:=cadders:PatchString(cadderstring);
  StubApiCDocumentFunction(returntype,fname,fname2,args);
];

StubApiCFunction(returntype,fname,fname2,args) :=
[
  cfuncs:= cfuncs:PatchString(funcstring);
  cadders:=cadders:PatchString(cadderstring);
  StubApiCDocumentFunction(returntype,fname,fname2,args);
];


StubApiCFile(file):=
[
  ToFile(file:".cc")WriteString(PatchString(fileapi));
  ToFile(file:".description")WriteString(cremarks);
];
